mod parser;
pub mod preprocess;
mod variant_ext;

use godot::{global::Error, prelude::*};
use parser::Parser;
use preprocess::PreProcessor;

struct GdapExtension;

#[gdextension(entry_point = gdap_init)]
unsafe impl ExtensionLibrary for GdapExtension {}

#[derive(GodotClass)]
#[class(init, base = Resource)]
pub struct Gdap {
    pub val: Variant,
    base: Base<Resource>,
}

#[godot_api]
impl Gdap {
    #[func]
    pub fn from_ast(ast: VariantArray) -> Gd<Self> {
        Gd::from_init_fn(|base| Self { val: PreProcessor::new().process(ast.to_variant()).unwrap_or_default(), base })
    }

    #[func]
    pub fn stringify(array: VariantArray) -> GString {
        unimplemented!()
    }

    #[func]
    pub fn eval(env: VariantArray, body: VariantArray) -> Variant {
        unimplemented!()
    }

    #[func]
    pub fn parse(&mut self, source: GString) -> Error {
        let mut parser = Parser::new(source.chars());
        match parser.parse() {
            Ok(ast) => {
                let p = PreProcessor::new();
                self.val = match p.process(ast) {
                    Ok(v) => v,
                    _ => return Error::ERR_PARSE_ERROR,
                };
                Error::OK
            }
            Err(e) => e,
        }
    }

    #[func]
    pub fn get_value(&self) -> Variant {
        self.val.clone()
    }

    #[func]
    pub fn execute(&self, env: VariantArray) -> Variant {
        if self.val.is_nil() {
            return Variant::nil();
        }

        if self.val.get_type() == VariantType::ARRAY && self.val.to::<VariantArray>().is_empty() {
            return Variant::nil();
        }
        unimplemented!()
    }
}
